#include "Water_Level.h";
#include "Aquarium_Devices.h";

extern LiquidCrystal     lcd;
extern Clock             clock;
extern Aquarium_Modes    aquarium_modes;

prog_char Water_Level_Error_0[] PROGMEM = "Water Level:";
prog_char Water_Level_Error_1[] PROGMEM = " Bottom Float Alert";
prog_char Water_Level_Error_2[] PROGMEM = " Top Float Alert";


prog_char Floats_Names_1[] PROGMEM ="Bottom Float";
prog_char Floats_Names_2[] PROGMEM ="Top Float";
prog_char Floats_Names_3[] PROGMEM ="Change Float";


PROGMEM const char *Floats_Names_table[] = 
{   
  Floats_Names_1,
  Floats_Names_2,
  Floats_Names_3
};



PROGMEM const char *Water_Level_Errors_Table[] = 
{   
  Water_Level_Error_0,
  Water_Level_Error_1,
  Water_Level_Error_2
};

void  Water_Level::Print_Float_Name(byte Float_Num){
  strcpy_P(buffer, (char*)pgm_read_word(&(  Floats_Names_table[Float_Num]     )));
  lcd.print(buffer );
}


bool  Water_Level::Get_Float_Status(byte Float_Num){
  switch(Float_Num){
    case 0: return Is_Bottom_Float_On();
    case 1: return Is_Top_Float_On();
    case 2: return Is_Water_Change_Bottom_Float_On();
  };
  return false;
}



byte Water_Level::Get_Number_Of_Print_Alerts(){
  return  Top_Float_Alert + Bottom_Float_Alert +1;
}

void  Water_Level::Print_Alerts(byte Line){
  if ( Line == 0 ){
    strcpy_P(buffer, (char*)pgm_read_word(&(  Water_Level_Errors_Table[  0 ]     )));
    lcd.print(buffer );
  }
  else {
    if ( Line == 1 ){
       if (Bottom_Float_Alert){
        strcpy_P(buffer, (char*)pgm_read_word(&(  Water_Level_Errors_Table[  1 ]     )));
        lcd.print(buffer );
       }else{
        strcpy_P(buffer, (char*)pgm_read_word(&(  Water_Level_Errors_Table[  2 ]     )));
        lcd.print(buffer );
       }
    } else {
        strcpy_P(buffer, (char*)pgm_read_word(&(  Water_Level_Errors_Table[  2 ]     )));
        lcd.print(buffer );
    }
   
  }

   
}

bool Water_Level::Is_Water_Change_Bottom_Float_On(){
  return !digitalRead(Water_Change_Bottom_Float_Pin_IN);
}

bool Water_Level::Is_Top_Float_On(){
  return !digitalRead(Water_Level_Top_Float_Pin_IN);
}

bool Water_Level::Is_Bottom_Float_On(){
  return !digitalRead(Water_Level_Bottom_Float_Pin_IN);
}


void Water_Level::init(){
  int address = EEPROM_WATER_LEVEL_ADDRESS_START;
  pinMode(Water_Level_Top_Float_Pin_IN, INPUT) ;
  pinMode(Water_Level_Bottom_Float_Pin_IN, INPUT);
  pinMode(Water_Level_Osmosis_Refull_Pin_OUT,OUTPUT);
 
  OnOff = EEPROM.read(address++) ;
  Modes = EEPROM.read(address++) ;

  Osmosis_Refull_OnOff = EEPROM.read(address++) ; 
  Osmosis_Refull_Modes = EEPROM.read(address++) ; 
  
 
  Clear_Alerts();

}

void Water_Level::Save_To_EEPROM(){
  int address = EEPROM_WATER_LEVEL_ADDRESS_START;

  EEPROM.write(address++, OnOff) ;
  EEPROM.write(address++, Modes) ;
   
  EEPROM.write(address++, Osmosis_Refull_OnOff) ;
  EEPROM.write(address++, Osmosis_Refull_Modes) ;
  

}


void Water_Level::update(){
  byte cur_mode = aquarium_modes.get_Aquarium_mode() ;

  if(Check_Modes(cur_mode)){
    
    if(Is_Bottom_Float_On() == false ){
      Bottom_Float_Alert = 1;
    }
 
    if(Is_Top_Float_On() == true ){
      Top_Float_Alert = 1;
    }
  }
  
  switch(Osmosis_Refull_OnOff){
    case OSMOSIS_REFUL_MODE_ON: 
       resume_Osmosis_Refull();
       break;
    case OSMOSIS_REFUL_MODE_OFF: 
       stop_Osmosis_Refull();  
       break;
    case OSMOSIS_REFUL_MODE_AUTO: 
       if(Top_Float_Alert || !Check_Osmosis_Refull_Modes(cur_mode) ){
          stop_Osmosis_Refull();  
       } else {
          resume_Osmosis_Refull();
       }
       break;
     };
   
}

void Water_Level::Clear_Alerts(){
  Top_Float_Alert = 0;
  Bottom_Float_Alert = 0;
}

bool Water_Level::Check_Modes(byte Mode){
  if ( OnOff == true ){
    return bitRead(Modes,Mode ) == 1;// true;//
  }
  return false;
}

bool Water_Level::Check_Osmosis_Refull_Modes(byte Mode){
  if ( Osmosis_Refull_OnOff != OSMOSIS_REFUL_MODE_OFF ){
    return bitRead(Osmosis_Refull_Modes,Mode ) == 1;
  }
  return false;
}


void Water_Level::stop_Osmosis_Refull(){
  digitalWrite(Water_Level_Osmosis_Refull_Pin_OUT, HIGH);    
}


void Water_Level::resume_Osmosis_Refull(){
  digitalWrite(Water_Level_Osmosis_Refull_Pin_OUT, LOW);    
}






























